home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * FileMon - File System Monitor for Windows NT
- *
- * Copyright (c) 1996 Mark Russinovich and Bryce Cogswell
- *
- * You have the right to take this code and use it in whatever
- * way you wish.
- *
- * PROGRAM: FileMon.c
- *
- * PURPOSE: Communicates with the FileMon driver to display
- * file system activity information.
- *
- ******************************************************************************/
- #define UNICODE 1
- #include <windows.h> // includes basic windows functionality
- #include <windowsx.h>
- #include <commctrl.h> // includes the common control header
- #include <stdio.h>
- #include <string.h>
- #include <winioctl.h>
- #include "resource.h"
- #include "ioctlcmd.h"
-
- #include "instdrv.h"
-
- // Set this to 0 for a non-processor specific version that does not get
- // process names from the device driver
- #define GETPROCESS 1
-
- // Variables/definitions for the driver that performs the actual monitoring.
- #define SYS_FILE TEXT("FILEMON.SYS")
- #define SYS_NAME TEXT("FILEMON")
- static HANDLE sys_handle = INVALID_HANDLE_VALUE;
-
-
- // Drive type names
- #define DRVUNKNOWN 0
- #define DRVFIXED 1
- #define DRVREMOTE 2
- #define DRVRAM 3
- #define DRVCD 4
- #define DRVREMOVE 5
- TCHAR DrvNames[][32] = {
- TEXT("UNKNOWN"),
- TEXT("FIXED"),
- TEXT("REMOTE"),
- TEXT("RAM"),
- TEXT("CD"),
- TEXT("REMOVEABLE"),
- };
-
-
- // Buffer into which driver can copy statistics
- char Stats[ MAX_STORE ];
- // Current fraction of buffer filled
- DWORD StatsLen;
-
- // Application instance handle
- HINSTANCE hInst;
-
- // Misc globals
- HWND hWndList;
- BOOLEAN Capture = TRUE;
- BOOLEAN Autoscroll = TRUE;
-
- // For info saving
- TCHAR szFileName[256];
- BOOLEAN FileChosen = FALSE;
-
- // General buffer for storing temporary strings
- static TCHAR msgbuf[ 257 ];
-
- // General cursor manipulation
- HCURSOR hSaveCursor;
- HCURSOR hHourGlass;
-
- // procs
- long APIENTRY MainWndProc( HWND, UINT, UINT, LONG );
- BOOL APIENTRY About( HWND, UINT, UINT, LONG );
-
- //functions
- BOOL InitApplication( HANDLE );
- HWND InitInstance( HANDLE, int );
- DWORD Hook_Drives( HMENU DriveMenu, DWORD MaxDriveSet, DWORD CurDriveSet );
- HWND CreateList( HWND );
- void UpdateStatistics( HWND hWnd, HWND hWndList, BOOL Clear );
- int CALLBACK ListCompareProc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );
- void SaveFile( HWND hDlg, HWND listbox, BOOLEAN SaveAs );
-
-
- /******************************************************************************
- *
- * FUNCTION: Abort:
- *
- * PURPOSE: Handles emergency exit conditions.
- *
- *****************************************************************************/
- void Abort( HWND hWnd, TCHAR * Msg )
- {
- UnloadDeviceDriver( SYS_NAME );
- MessageBox( hWnd, Msg, TEXT("FileMon"), MB_OK );
- PostQuitMessage( 1 );
- }
-
-
- /****************************************************************************
- *
- * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
- *
- * PURPOSE: calls initialization function, processes message loop
- *
- ****************************************************************************/
- int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow )
- {
- MSG msg;
- HWND hWnd;
-
- if ( ! InitApplication( hInstance ) )
- return FALSE;
-
- // initializations that apply to a specific instance
- if ( (hWnd = InitInstance( hInstance, nCmdShow )) == NULL )
- return FALSE;
-
-
- // acquire and dispatch messages until a WM_QUIT message is received.
- while ( GetMessage( &msg, NULL, 0, 0 ) ) {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- return msg.wParam;
- }
-
-
- /****************************************************************************
- *
- * FUNCTION: InitApplication(HANDLE)
- *
- * PURPOSE: Initializes window data and registers window class
- *
- ****************************************************************************/
- BOOL InitApplication( HANDLE hInstance )
- {
- WNDCLASS wc;
-
- // Fill in window class structure with parameters that describe the
- // main (statistics) window.
- wc.style = 0;
- wc.lpfnWndProc = (WNDPROC)MainWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon( hInstance, TEXT("APPICON") );
- wc.hCursor = LoadCursor( NULL, IDC_ARROW );
- wc.hbrBackground = GetStockObject( LTGRAY_BRUSH );
- wc.lpszMenuName = TEXT("LISTMENU");
- wc.lpszClassName = TEXT("FileMonClass");
- if ( ! RegisterClass( &wc ) )
- return FALSE;
-
- return TRUE;
- }
-
-
- /****************************************************************************
- *
- * FUNCTION: InitInstance(HANDLE, int)
- *
- * PURPOSE: Saves instance handle and creates main window
- *
- ****************************************************************************/
- HWND InitInstance( HANDLE hInstance, int nCmdShow )
- {
- HWND hWndMain;
-
- hInst = hInstance;
-
- hWndMain = CreateWindow( TEXT("FileMonClass"), TEXT("NT File Monitor"),
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, hInstance, NULL );
-
- // if window could not be created, return "failure"
- if ( ! hWndMain )
- return NULL;
-
- // make the window visible; update its client area; and return "success"
- ShowWindow( hWndMain, nCmdShow );
- UpdateWindow( hWndMain );
- return hWndMain;
- }
-
-
- /****************************************************************************
- *
- * FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
- *
- * PURPOSE: Processes messages for the statistics window.
- *
- ****************************************************************************/
- LONG APIENTRY MainWndProc( HWND hWnd, UINT message, UINT wParam, LONG lParam)
- {
- static DWORD CurDriveSet = 0;
- static DWORD MaxDriveSet = 0;
- static HMENU DriveMenu;
- ULONG irpcount;
- DWORD nb;
- DWORD drive, drivetype;
- TCHAR Path[ 256 ];
- TCHAR name[32];
-
- switch ( message ) {
-
- case WM_CREATE:
-
- // get hourglass icon ready
- hHourGlass = LoadCursor( NULL, IDC_WAIT );
-
- // post hourglass icon
- SetCapture(hWnd);
- hSaveCursor = SetCursor(hHourGlass);
-
- // Create the ListBox within the main window
- hWndList = CreateList( hWnd );
- if ( hWndList == NULL )
- MessageBox( NULL, TEXT("List not created!"), NULL, MB_OK );
-
- // open the handle to the device
- GetCurrentDirectory( sizeof Path, Path );
- wsprintf( Path+lstrlen(Path), TEXT("\\%s"), SYS_FILE );
- if ( ! LoadDeviceDriver( SYS_NAME, Path, &sys_handle ) ) {
- wsprintf( msgbuf, TEXT("Opening %s (%s): error %d"), SYS_NAME, Path,
- GetLastError( ) );
- Abort( hWnd, msgbuf );
- }
-
- // Have driver zero information
- if ( ! DeviceIoControl( sys_handle, FILEMON_zerostats,
- NULL, 0, NULL, 0, &nb, NULL ) )
- {
- Abort( hWnd, TEXT("Couldn't access device driver") );
- return TRUE;
- }
-
- // Create a pop-up menu item with the drives
- DriveMenu = CreateMenu();
-
- // Get available drives we can monitor
- MaxDriveSet = GetLogicalDrives();
- CurDriveSet = MaxDriveSet;
- for ( drive = 0; drive < 32; ++drive ) {
- if ( MaxDriveSet & (1 << drive) ) {
- wsprintf( name, TEXT("%c:\\"), 'A'+drive );
- switch ( GetDriveType( name ) ) {
- // We don't like these: remove them
- case 0: // The drive type cannot be determined.
- case 1: // The root directory does not exist.
- drivetype = DRVUNKNOWN;
- CurDriveSet &= ~(1 << drive);
- break;
- case DRIVE_REMOVABLE: // The drive can be removed from the drive.
- drivetype = DRVREMOVE;
- CurDriveSet &= ~(1 << drive);
- break;
- case DRIVE_CDROM: // The drive is a CD-ROM drive.
- drivetype = DRVCD;
- CurDriveSet &= ~(1 << drive);
- break;
-
- // We like these types
- case DRIVE_FIXED: // The disk cannot be removed from the drive.
- drivetype = DRVFIXED;
- break;
- case DRIVE_REMOTE: // The drive is a remote (network) drive.
- drivetype = DRVREMOTE;
- break;
- case DRIVE_RAMDISK: // The drive is a RAM disk.
- drivetype = DRVRAM;
- break;
- }
- wsprintf( name, TEXT("Drive &%c: (%s)"), 'A'+drive, DrvNames[drivetype] );
- InsertMenu( DriveMenu, 0xFFFFFFFF, MF_BYPOSITION|MF_STRING,
- IDC_DRIVE+drive, name );
- }
- }
- // Insert into top-level menu
- InsertMenu( GetMenu( hWnd ), 2, MF_BYPOSITION|MF_POPUP|MF_STRING,
- (UINT)DriveMenu, TEXT("&Drives") );
-
- // Have driver hook the selected drives
- CurDriveSet = Hook_Drives( DriveMenu, MaxDriveSet, CurDriveSet );
-
- // Start up timer to periodically update screen
- SetTimer( hWnd, 1, 500/*ms*/, NULL );
-
- // Initialization done
- SetCursor( hSaveCursor );
- ReleaseCapture();
- return 0;
-
- case WM_NOTIFY:
- // Make sure its intended for us
- if ( wParam == ID_LIST ) {
- NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
- switch ( pNm->hdr.code ) {
-
- case LVN_BEGINLABELEDIT:
- // Don't allow editing of information
- return TRUE;
- }
- }
- return 0;
-
- case WM_COMMAND:
-
- switch ( LOWORD( wParam ) ) {
-
- // stats related commands to send to driver
- case IDM_CLEAR:
- // Have driver zero information
- if ( ! DeviceIoControl( sys_handle, FILEMON_zerostats,
- NULL, 0, NULL, 0, &nb, NULL ) )
- {
- Abort( hWnd, TEXT("Couldn't access device driver") );
- return TRUE;
- }
- // Update statistics windows
- UpdateStatistics( hWnd, hWndList, TRUE );
- return 0;
-
- case IDM_CAPTURE:
- // Read statistics from driver
- Capture = !Capture;
- CheckMenuItem( GetMenu(hWnd), IDM_CAPTURE,
- MF_BYCOMMAND|(Capture?MF_CHECKED:MF_UNCHECKED) );
- return 0;
-
- case IDM_AUTOSCROLL:
- Autoscroll = !Autoscroll;
- CheckMenuItem( GetMenu(hWnd), IDM_AUTOSCROLL,
- MF_BYCOMMAND|(Autoscroll?MF_CHECKED:MF_UNCHECKED) );
- return 0;
-
- case IDM_EXIT:
- // Close ourself
- SendMessage( hWnd, WM_CLOSE, 0, 0 );
- return 0;
-
- case IDM_ABOUT:
- // Show the names of the authors
- DialogBox( hInst, TEXT("AboutBox"), hWnd, (DLGPROC)About );
- return 0;
-
- case IDM_SAVE:
- SaveFile( hWnd, hWndList, FALSE );
- return 0;
-
- case IDM_SAVEAS:
- SaveFile( hWnd, hWndList, TRUE );
- return 0;
-
- default:
- drive = LOWORD( wParam ) - IDC_DRIVE;
- if ( drive < 32 ) {
- // Toggle status
- CurDriveSet ^= (1 << drive);
- // Have driver hook the selected drives
- CurDriveSet = Hook_Drives( DriveMenu, MaxDriveSet, CurDriveSet );
- return 0;
- } else {
- // Default behavior
- return DefWindowProc( hWnd, message, wParam, lParam );
- }
- }
- break;
-
- case WM_TIMER:
- // Time to query the device driver for more data
- if ( Capture ) {
- for (;;) {
- // Have driver fill Stats buffer with information
- if ( ! DeviceIoControl( sys_handle, FILEMON_getstats,
- NULL, 0, &Stats, sizeof Stats,
- &StatsLen, NULL ) )
- {
- Abort( hWnd, TEXT("Couldn't access device driver") );
- return TRUE;
- }
- if ( StatsLen == 0 )
- break;
- // Update statistics windows
- UpdateStatistics( hWnd, hWndList, FALSE );
- }
- }
- return 0;
-
- case WM_SIZE:
- // Move or resize the List
- MoveWindow( hWndList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE );
- return 0;
-
- case WM_CLOSE:
- // see if the driver can unload
- if ( ! DeviceIoControl( sys_handle, FILEMON_unloadquery,
- NULL, 0, NULL, 0,
- &irpcount, NULL ) ) {
- Abort( hWnd, TEXT("Couldn't access device driver") );
- return TRUE;
- }
- if( irpcount ) {
- wsprintf( msgbuf, TEXT("The Filemon device driver cannot unload\n")
- TEXT("at this time due to oustanding requests.\n\n")
- TEXT("Do you wish to exit the GUI now?"));
- if( MessageBox( hWnd, msgbuf, TEXT("Filemon"), MB_ICONSTOP|MB_YESNO ) == IDNO )
- return 0;
- CloseHandle( sys_handle );
- } else {
- CloseHandle( sys_handle );
- if ( ! UnloadDeviceDriver( SYS_NAME ) ) {
- wsprintf( msgbuf, TEXT("Error unloading \"%s\""), SYS_NAME );
- MessageBox( hWnd, msgbuf, TEXT("FileMon"), MB_OK );
- }
- }
- return DefWindowProc( hWnd, message, wParam, lParam );
-
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
-
- default:
- // Default behavior
- return DefWindowProc( hWnd, message, wParam, lParam );
- }
- return 0;
- }
-
-
- /******************************************************************************
- *
- * FUNCTION: Hook_Drives
- *
- * PURPOSE: Hook the currently selected drives, updating menu checks
- *
- ******************************************************************************/
- DWORD Hook_Drives( HMENU DriveMenu, DWORD MaxDriveSet, DWORD CurDriveSet )
- {
- DWORD nb;
- DWORD drive;
-
- // Tell device driver which drives to monitor
- if ( ! DeviceIoControl( sys_handle, FILEMON_setdrives,
- &CurDriveSet, sizeof CurDriveSet,
- &CurDriveSet, sizeof CurDriveSet,
- &nb, NULL ) )
- return 0;
-
- // Update menu items
- for ( drive = 0; drive < 32; ++drive )
- if ( MaxDriveSet & (1<<drive) ) {
- if ( CurDriveSet & (1<<drive) )
- CheckMenuItem( DriveMenu, IDC_DRIVE+drive, MF_BYCOMMAND|MF_CHECKED );
- else
- CheckMenuItem( DriveMenu, IDC_DRIVE+drive, MF_BYCOMMAND|MF_UNCHECKED );
- }
- return CurDriveSet;
- }
-
-
- /******************************************************************************
- *
- * FUNCTION: Split
- *
- * PURPOSE: Split a delimited line into components
- *
- ******************************************************************************/
- int Split( char * line, char delimiter, char * items[] )
- {
- int cnt = 0;
-
- for (;;) {
- // Add prefix to list of components
- items[cnt++] = line;
-
- // Check for more components
- line = strchr( line, delimiter );
- if ( line == NULL )
- return cnt;
-
- // Terminate previous component and move to next
- *line++ = '\0';
- }
- }
-
-
- /******************************************************************************
- *
- * FUNCTION: ListAppend
- *
- * PURPOSE: Add a new line to List window
- *
- ******************************************************************************/
- BOOL List_Append( HWND hWndList, DWORD seq, char * line )
- {
- LV_ITEM lvI; // list view item structure
- int row;
- char * items[20];
- int itemcnt = 0;
-
- // Split line into columns
- itemcnt = Split( line, '\t', items );
- if ( itemcnt == 0 )
- return TRUE;
-
- // Determine row number for request
- if ( *items[0] ) {
- // Its a new request. Put at end.
- row = 0x7FFFFFFF;
- } else {
- // Its a status. Locate its associated request.
- lvI.mask = LVIF_PARAM;
- lvI.iSubItem = 0;
- for ( row = ListView_GetItemCount(hWndList) - 1; row >= 0; --row ) {
- lvI.iItem = row;
- if ( ListView_GetItem( hWndList, &lvI ) && (DWORD)lvI.lParam == seq )
- break;
- }
- if ( row == -1 )
- // No request associated with status.
- return TRUE;
- }
-
- // Sequence number if a new item
- if ( *items[0] ) {
- wsprintf( msgbuf, TEXT("%d"), seq );
- lvI.mask = LVIF_TEXT | LVIF_PARAM;
- lvI.iItem = row;
- lvI.iSubItem = 0;
- lvI.pszText = msgbuf;
- lvI.cchTextMax = lstrlen( lvI.pszText ) + 1;
- lvI.lParam = seq;
- row = ListView_InsertItem( hWndList, &lvI );
- if ( row == -1 ) {
- wsprintf( msgbuf, TEXT("Error adding item %d to list view"), seq );
- MessageBox( hWndList, msgbuf, TEXT("FileMon Error"), MB_OK );
- return FALSE;
- }
- }
- #if GETPROCESS
- // Process name
- if ( itemcnt>0 && *items[0] ) {
- OemToChar( items[0], msgbuf );
- ListView_SetItemText( hWndList, row, 1, msgbuf );
- }
- #endif
- // Request type
- if ( itemcnt>1 && *items[1] ) {
- OemToChar( items[1], msgbuf );
- ListView_SetItemText( hWndList, row, 1+GETPROCESS, msgbuf );
- }
-
- // Path
- if ( itemcnt>2 && *items[2] ) {
- OemToChar( items[2], msgbuf );
- ListView_SetItemText( hWndList, row, 2+GETPROCESS, msgbuf );
- }
-
- // Result
- if ( itemcnt>4 && *items[4] ) {
- OemToChar( items[4], msgbuf );
- ListView_SetItemText( hWndList, row, 3+GETPROCESS, msgbuf );
- }
-
- // Additional
- if ( itemcnt>3 && *items[3] ) {
- OemToChar( items[3], msgbuf );
- ListView_SetItemText( hWndList, row, 4+GETPROCESS, msgbuf );
- }
-
- return TRUE;
- }
-
-
- /******************************************************************************
- *
- * FUNCTION: UpdateStatistics
- *
- * PURPOSE: Clear the statistics window and refill it with the current
- * contents of the statistics buffer. Does not refresh the
- * buffer from the device driver.
- *
- ******************************************************************************/
- void UpdateStatistics( HWND hWnd, HWND hWndList, BOOL Clear )
- {
- PENTRY ptr;
-
- // Just return if nothing to do
- if ( !Clear && StatsLen < sizeof(int)+2 )
- return;
-
- // Start with empty list
- if ( Clear )
- ListView_DeleteAllItems( hWndList );
-
-
- // Add all List items from Stats[] data
- for ( ptr = (void *)Stats; (char *)ptr < Stats+StatsLen; ) {
- // Add to list
- ULONG len = strlen(ptr->text);
- List_Append( hWndList, ptr->seq, ptr->text );
- ptr = (void *)(ptr->text + len + 1);
- }
-
- // Empty the buffer
- StatsLen = 0;
-
- // Scroll so newly added items are visible
- if ( Autoscroll )
- ListView_EnsureVisible( hWndList, ListView_GetItemCount(hWndList)-1, FALSE );
- }
-
-
- /****************************************************************************
- *
- * FUNCTION: CreateListView(HWND)
- *
- * PURPOSE: Creates the statistics list view window and initializes it
- *
- ****************************************************************************/
- HWND CreateList( HWND hWndParent )
- {
- HWND hWndList; // handle to list view window
- RECT rc; // rectangle for setting size of window
- LV_COLUMN lvC; // list view column structure
- DWORD j;
- static struct {
- TCHAR * Label; // title of column
- DWORD Width; // width of column in pixels
- DWORD Fmt;
- } column[] = {
- { TEXT("#"), 35 },
- #if GETPROCESS
- { TEXT("Process"), 100 },
- #endif
- { TEXT("Request"), 150 },
- { TEXT("Path"), 200 },
- { TEXT("Result"), 70 },
- { TEXT("Other"), 150 },
- };
-
- // Ensure that the common control DLL is loaded.
- InitCommonControls();
-
- // Get the size and position of the parent window.
- GetClientRect( hWndParent, &rc );
-
- // Create the list view window
- hWndList = CreateWindowEx( 0L, WC_LISTVIEW, TEXT(""),
- WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT |
- WS_EX_CLIENTEDGE, // styles
- 0, 0, rc.right - rc.left, rc.bottom - rc.top,
- hWndParent, (HMENU)ID_LIST, hInst, NULL );
- if ( hWndList == NULL )
- return NULL;
-
- // Initialize columns
- lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
- lvC.fmt = LVCFMT_LEFT; // left-align column
-
- // Add the columns.
- for ( j = 0; j < sizeof column/sizeof column[0]; ++j ) {
- lvC.iSubItem = j;
- lvC.cx = column[j].Width;
- lvC.pszText = column[j].Label;
- if ( ListView_InsertColumn( hWndList, j, &lvC ) == -1 )
- return NULL;
- }
-
- return hWndList;
- }
-
-
- /****************************************************************************
- *
- * FUNCTION: SaveFile()
- *
- * PURPOSE: Lets the user go select a file.
- *
- ****************************************************************************/
- void SaveFile( HWND hWnd, HWND ListBox, BOOLEAN SaveAs )
- {
- OPENFILENAME SaveFileName;
- TCHAR szFile[256] = TEXT(""), fieldtext[256], output[1024];
- FILE *hFile;
- int numitems;
- int row, subitem;
-
- if( SaveAs || !FileChosen ) {
- SaveFileName.lStructSize = sizeof (SaveFileName);
- SaveFileName.hwndOwner = hWnd;
- SaveFileName.hInstance = (HANDLE) hInst;
- SaveFileName.lpstrFilter = TEXT("File Info (*.FIL)\0*.FIL\0All (*.*)\0*.*\0");
- SaveFileName.lpstrCustomFilter = (LPTSTR)NULL;
- SaveFileName.nMaxCustFilter = 0L;
- SaveFileName.nFilterIndex = 1L;
- SaveFileName.lpstrFile = szFile;
- SaveFileName.nMaxFile = 256;
- SaveFileName.lpstrFileTitle = NULL;
- SaveFileName.nMaxFileTitle = 0;
- SaveFileName.lpstrInitialDir = NULL;
- SaveFileName.lpstrTitle = TEXT("Save File Info...");
- SaveFileName.nFileOffset = 0;
- SaveFileName.nFileExtension = 0;
- SaveFileName.lpstrDefExt = TEXT("*.fil");
- SaveFileName.lpfnHook = NULL;
- SaveFileName.Flags = OFN_LONGNAMES|OFN_HIDEREADONLY;
-
- if( !GetSaveFileName( &SaveFileName ))
- return;
- } else
- // open previous szFile
- wcscpy( szFile, szFileName );
-
- // open the file
- hFile = _wfopen( szFile, TEXT("w") );
- if( !hFile ) {
- MessageBox( NULL, TEXT("Create File Failed."),
- TEXT("Save Error"), MB_OK|MB_ICONSTOP );
- return;
- }
-
- // post hourglass icon
- SetCapture(hWnd);
- hSaveCursor = SetCursor(hHourGlass);
-
- numitems = ListView_GetItemCount(ListBox);
- for ( row = 0; row < numitems; row++ ) {
- output[0] = 0;
- for( subitem = 0; subitem < 6; subitem++ ) {
- fieldtext[0] = 0;
- ListView_GetItemText( ListBox, row, subitem, fieldtext, 256 );
- wcscat( output, fieldtext );
- wcscat( output, TEXT("\t") );
- }
- fwprintf( hFile, TEXT("%s\n"), output );
- }
- fclose( hFile );
- wcscpy( szFileName, szFile );
- FileChosen = TRUE;
- SetCursor( hSaveCursor );
- ReleaseCapture();
- }
-
-
-
- /****************************************************************************
- *
- * FUNCTION: About
- *
- * PURPOSE: Processes messages for "About" dialog box
- *
- ****************************************************************************/
-
- BOOL APIENTRY About( HWND hDlg, UINT message, UINT wParam, LONG lParam )
- {
- switch ( message ) {
- case WM_INITDIALOG:
- return TRUE;
-
- case WM_COMMAND:
- if ( LOWORD( wParam ) == IDOK ) {
- EndDialog( hDlg, TRUE );
- return TRUE;
- }
- break;
- }
- return FALSE;
- }
-